package com.kly.sc.api.application.controller.homepage;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.api.Response;
import com.fqgj.common.api.annotations.ParamsValidate;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.StringUtils;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.common.collect.Maps;
import com.jsoniter.output.JsonStream;
import com.kly.dto.MemberDto;
import com.kly.dto.UserVasPurchasesDto;
import com.kly.enums.Benefits;
import com.kly.sc.api.application.constant.ApiRedisKeys;
import com.kly.sc.api.application.controller.user.request.RecommendUsersRequest;
import com.kly.sc.api.application.controller.user.response.RecommendUserResp;
import com.kly.sc.api.application.helper.RequestLocalInfo;
import com.kly.sc.api.application.service.user.HasMemberBenefitsValidationService;
import com.kly.sc.api.application.service.utils.BaseComponent;
import com.kly.sc.api.application.utils.BaseUtils;
import com.kly.sc.api.application.utils.RpcUtils;
import com.kly.sc.api.integration.impl.RCClientImpl;
import com.kly.service.MemberBenefitsService;
import com.kly.service.UserVasPurchasesService;
import com.kly.user.constant.RedisKey;
import com.kly.user.dto.RecommendUserDto;
import com.kly.user.dto.UserBehaviorReq;
import com.kly.user.enums.GenderEnum;
import com.kly.user.enums.OnlineStatus;
import com.kly.user.enums.RememberTime;
import com.kly.user.service.BehaviorService;
import com.kly.user.service.WlmService;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 首页
 *
 * @author linqu
 */
@RestController
@RequestMapping("/api/home")
public class HomepageController extends BaseComponent {

    private static final Log logger = LogFactory.getLog(HomepageController.class);

    @Resource
    private WlmService wlmService;

    @Resource
    private RCClientImpl rcClient;

    @Resource
    RedisClient redisClient;

    @Resource
    BaseComponent baseComponent;

    @Resource
    private BehaviorService behaviorService;

    @Resource
    private UserVasPurchasesService userVasPurchasesService;

    @Resource
    private MemberBenefitsService memberBenefitsService;

    @NacosValue(value = "${homepage.page.size}", autoRefreshed = true)
    private Integer recordNum;

    @NacosValue(value = "${homepage.newUser.turnOns}", autoRefreshed = true)
    private Integer newUserSize;

    @NacosValue(value = "${homepage.oldUser.turnOns}", autoRefreshed = true)
    private Integer oldUserSize;

    @NacosValue(value = "${homepage.cache.model.num}", autoRefreshed = true)
    private Integer cacheHomepageNum;
    @Resource
    HasMemberBenefitsValidationService hasMemberBenefitsValidationService;
    /**
     * 倒计时间延迟到权益发放后
     */
    @NacosValue(value = "${countdown.delay.time:5400}")
    private Long countDownDelayTime;
    /**
     * 无首页浏览权益时的提示文案
     */
    @NacosValue(value = "${reached.browse.limit.title:OOPS! No More Match}")
    private String reachedBrowseLimitTitle;
    /**
     * 无首页浏览权益时的提示文案
     */
    @NacosValue(value = "${reached.browse.limit.content:Don't want to wait?Unlock now to find more fun!}")
    private String reachedBrowseLimitContent;
    /**
     * 无首页浏览权益时展示的图片
     */
    @NacosValue(value = "${reached.browse.limit.image}", autoRefreshed = true)
    private String reachedBrowseLimitImage;
    /**
     * 无首页浏览权益时展示的封面图
     */
    @NacosValue(value = "${reached.browse.limit.default.image}", autoRefreshed = true)
    private String reachedBrowseLimitDefaultImage;


    private static final int ZERO = 0;

    private static final int ONE = 1;

    /**
     * @param recommendUsersRequest 首页推荐用户展示记录数
     * @return 返回推荐用户
     */
    @ResponseBody
    @RequestMapping(value = "/homepage")
    @ParamsValidate
    public Response homepage(@RequestBody RecommendUsersRequest recommendUsersRequest) {
//        try {
//            logger.info("== 请求首页1 开始 ==,request:{}", JsonStream.serialize(recommendUsersRequest));
//        } catch (Exception e) {
//            logger.info("== 请求首页2 开始 参数json异常==", e);
//        }
        long start = System.currentTimeMillis();
        recommendUsersRequest.setRecordNum(recordNum);

        String userCode = RequestLocalInfo.getCurrentUser().getUserCode();
        List<Integer> turnOnsList = RequestLocalInfo.getCurrentUser().getTurnOnsList();

        Map<String, Object> res = Maps.newHashMap();

        MemberDto memberDto = baseComponent.retrieveMemberFromCacheOrService(userCode);

        final Integer remainingBrowseNum = hasMemberBenefitsValidationService.queryBenefitsByUserCode(Benefits.NUMBER_OF_USERS_BROWSED, userCode);
        res.put("ismember", memberDto != null);
        res.put("title", reachedBrowseLimitTitle);
        res.put("noticeMsg", reachedBrowseLimitContent);
        res.put("coverImage", reachedBrowseLimitImage);
        res.put("defaultCoverImage", reachedBrowseLimitDefaultImage);
        res.put("flashChatNum",getFlashChatNum(userCode));

        res.put("flashChatLimit",3);
        res.put("locationLimit",8);

        if (memberDto == null && remainingBrowseNum == 0) {
            res.put("preferentialFlag", 1);
            res.put("homepageList", new ArrayList<>());
            res.put("refreshTime", BaseUtils.getSeconds(1) + countDownDelayTime);
            res.put("newUserFlag", RequestLocalInfo.getCurrentUser().getNewUserFlag());
            return Response.ok(res);
        }

        res.put("remainingWlmNum", hasMemberBenefitsValidationService.queryBenefitsByUserCode(Benefits.NUMBER_OF_USERS_LIKED, userCode));
        res.put("remainingBrowseBNum", remainingBrowseNum);
        res.put("ismember", memberDto != null);
        res.put("turnOns", CollUtil.isNotEmpty(turnOnsList));
        res.put("newUserFlag", RequestLocalInfo.getCurrentUser().getNewUserFlag());
        if (super.showTurnOns()) {
            res.put("turnOnsLimit", 99999);
        } else {
            res.put("turnOnsLimit", redisClient.get(ApiRedisKeys.NEW_USER.getValue(), userCode) == null ? oldUserSize : newUserSize);
        }
//        logger.info("== 请求首页6 ==,cost:{}", System.currentTimeMillis() - start);
        Response<List<RecommendUserDto>> listResponse = wlmService.recommendUsers(userCode, recommendUsersRequest.getRecordNum());
//        logger.info("== 请求首页66 ==,cost:{}", System.currentTimeMillis() - start);
        final List<RecommendUserDto> recommendUserDtos = RpcUtils.getResult(listResponse);
//        logger.info("== 请求首页7 ==,cost:{}", System.currentTimeMillis() - start);
        if (CollectionUtils.isEmpty(recommendUserDtos)) {
            res.put("preferentialFlag", 0);
            res.put("homepageList", recommendUserDtos);
            return Response.ok(res);
        }

        final List<RecommendUserResp> recommendUsers = recommendUserDtos.stream().filter(Objects::nonNull).map(this::buildRecommendUserResp).filter(Objects::nonNull).collect(Collectors.toList());

        res.put("preferentialFlag", 0);
        res.put("homepageList", recommendUsers);

//        logger.info("== 请求首页8 ==,cost:{}", System.currentTimeMillis() - start);
        try {
            UserBehaviorReq userBehaviorReq = UserBehaviorReq.builder().userCode(userCode).actionType(99).build();
            behaviorService.doAction(userBehaviorReq);
//            logger.info("== 请求首页9 ==,cost:{}", System.currentTimeMillis() - start);
        } catch (Exception e) {
            logger.error("== 请求首页10 异常 ==,", e);
        }

        return Response.ok(res);
    }

    private Integer getFlashChatNum(String userCode) {
        try {
            //读取会员权益flash chat 数量
            Integer benefitsCount = RpcUtils.getResult(memberBenefitsService.getUserBenefitsCount(userCode, 1));

            final List<UserVasPurchasesDto> benefitList = RpcUtils.getResult(userVasPurchasesService.getAllUserBenefits(userCode));
            if (CollectionUtils.isEmpty(benefitList)) {
                return benefitsCount;
            }
            final UserVasPurchasesDto userVasPurchasesDto = benefitList.stream().filter(o -> 1 == o.getBenefitCode()).findAny().orElse(null);
            if (userVasPurchasesDto == null) {
                return benefitsCount;
            }
            final Integer usageCount = userVasPurchasesDto.getUsageCount();
            return (usageCount == null ? 0 : usageCount) + (benefitsCount == null ? 0 : benefitsCount);
        } catch (Exception e) {
            logger.error("getFlashChatNumError", e);
        }
        return 0;
    }


    private void cacheData(String userCode, List<RecommendUserResp> recommendUsers) {
        if (CollectionUtils.isEmpty(recommendUsers)) {
            return;
        }

        final Set<String> keys = redisClient.getRedisTemplate().keys(RedisKey.HOMEPAGE_BROWSE_FUZZY + userCode + "*");
        logger.info("fetchCacheKeys:{}, recommendUserSize:{}", JSONObject.toJSONString(keys), recommendUsers);
        if (recommendUsers.size() > cacheHomepageNum) {
            if (CollectionUtils.isNotEmpty(keys)) {
                keys.parallelStream().forEach(key -> redisClient.del((String) key));
            }
            for (int i = 0; i < cacheHomepageNum; i++) {
                final RecommendUserResp vo = recommendUsers.get(i);
                redisClient.setString(RedisKey.HOMEPAGE_BROWSE, vo.getFriendUserCode(), vo.getUserCode(), vo.getFriendUserCode());
                redisClient.expire(RedisKey.HOMEPAGE_BROWSE, (int) RememberTime.ONE_DAY.getTime(), vo.getUserCode(), vo.getFriendUserCode());
            }
        } else {
            if (CollectionUtils.isNotEmpty(keys)) {
                Integer needRemoveFromCacheKeySize = recommendUsers.size() + keys.size() - cacheHomepageNum;
                if (needRemoveFromCacheKeySize > 0) {
                    final List<String> keysList = new ArrayList<>(keys);
                    keysList.subList(0, needRemoveFromCacheKeySize).forEach(key -> redisClient.del(key));
                }
            }

            for (RecommendUserResp vo : recommendUsers) {
                redisClient.setString(RedisKey.HOMEPAGE_BROWSE, vo.getFriendUserCode(), vo.getUserCode(), vo.getFriendUserCode());
                redisClient.expire(RedisKey.HOMEPAGE_BROWSE, (int) RememberTime.ONE_DAY.getTime(), vo.getUserCode(), vo.getFriendUserCode());
            }

        }
    }

    private RecommendUserResp buildRecommendUserResp(RecommendUserDto o) {

        final String modelUserCode = redisClient.getString(RedisKey.HOMEPAGE_BROWSE, o.getUserCode(), o.getFriendUserCode());
        if (StringUtils.isNotEmpty(modelUserCode)) {
            return null;
        }
        RecommendUserResp resp = new RecommendUserResp();
        BeanUtils.copyProperties(o, resp);
        resp.setImages(o.getPersonalPhoto());
        resp.setOnlineDesc(o.getOnline() == null ? "" : OnlineStatus.fromType(o.getOnline()).getValue());
        resp.setLookingForDesc(GenderEnum.fromType(o.getLookingFor()).getValue());
        resp.setGenderDesc(GenderEnum.fromType(o.getGender()).getValue());
        resp.setNearby(String.valueOf(o.getNearby()));
        // 开关打开时，需要对turnOns隐藏处理
        if (super.showTurnOns()) {
            resp.setTurnOnsListSize(0);
        }

        resp.setState(o.getStateAbbr());
        resp.setCity(o.getCity());
        resp.setLat(o.getLat());
        resp.setLng(o.getLng());
        // 已经加载的用户存入缓存中
//        redisClient.setString(RedisKey.HOMEPAGE_BROWSE, o.getFriendUserCode(), o.getUserCode(), o.getFriendUserCode());
//        redisClient.expire(RedisKey.HOMEPAGE_BROWSE, 60 * 5, o.getUserCode(), o.getFriendUserCode());
        return resp;
    }

}
